from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import logging
import os
import shutil
import sys
import unittest

import secret
import util


__author__  = 'ZL <837806295@qq.com>'
__product__ = 'test'
__version__ = '3.0.0'
__date__    = '2023/04/08'


log = logging.getLogger(__product__)


class TestCase001(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.work_dir = util.get_test_subdir(__file__, cls.__name__)

    @classmethod
    def tearDownClass(cls):
        del cls.work_dir
        util.remove_test_subdir(__file__, cls.__name__)

    def setUp(self):
        self.work_dir = self.__class__.work_dir

    def tearDown(self):
        del self.work_dir

    def test_command(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" -h'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py')
                )
        )

        self.assertTrue(util.run(cmd))

class TestCase002(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.work_dir = util.get_test_subdir(__file__, cls.__name__)

    @classmethod
    def tearDownClass(cls):
        del cls.work_dir
        util.remove_test_subdir(__file__, cls.__name__)

    def setUp(self):
        self.work_dir = self.__class__.work_dir

    def tearDown(self):
        del self.work_dir

    def test_subcommand_encrypt(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" encrypt -h'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py')
                )
        )

        self.assertTrue(util.run(cmd))

class TestCase003(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.work_dir = util.get_test_subdir(__file__, cls.__name__)

    @classmethod
    def tearDownClass(cls):
        del cls.work_dir
        util.remove_test_subdir(__file__, cls.__name__)

    def setUp(self):
        self.work_dir = self.__class__.work_dir

    def tearDown(self):
        del self.work_dir

    def test_subcommand_decrypt(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" encrypt -h'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py')
                )
        )

        self.assertTrue(util.run(cmd))

class TestCase004(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.work_dir = util.get_test_subdir(__file__, cls.__name__)

    @classmethod
    def tearDownClass(cls):
        del cls.work_dir
        util.remove_test_subdir(__file__, cls.__name__)

    def setUp(self):
        self.work_dir = self.__class__.work_dir

    def tearDown(self):
        del self.work_dir

    def test_subcommand_list(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" list -h'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py')
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_list2(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" list "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    util.get_test_subdir(
                        __file__,
                        ['data', 'encrypted_file'])
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_list3(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" list -c "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    util.get_test_subdir(
                        __file__,
                        ['data', 'encrypted_file'])
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_list4(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" list -e "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    util.get_test_subdir(
                        __file__,
                        ['data', 'encrypted_file'])
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_list5(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" list -e -c "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    util.get_test_subdir(
                        __file__,
                        ['data', 'encrypted_file'])
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_list6(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" list -r decrypted "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    util.get_test_subdir(
                        __file__,
                        ['data', 'encrypted_file'])
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_list7(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" list -r decrypted -c "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    util.get_test_subdir(
                        __file__,
                        ['data', 'encrypted_file'])
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_list8(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" list -r encrypted "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    util.get_test_subdir(
                        __file__,
                        ['data', 'encrypted_file'])
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_list9(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" list -r encrypted -c "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    util.get_test_subdir(
                        __file__,
                        ['data', 'encrypted_file'])
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_list10(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" list -r special "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    util.get_test_subdir(
                        __file__,
                        ['data', 'encrypted_file'])
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_list11(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" list -r special -c "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    util.get_test_subdir(
                        __file__,
                        ['data', 'encrypted_file'])
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_list12(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" list -r empty "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    util.get_test_subdir(
                        __file__,
                        ['data', 'encrypted_file'])
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_list13(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" list -r empty -c "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    util.get_test_subdir(
                        __file__,
                        ['data', 'encrypted_file'])
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_list14(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" list -r both "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    util.get_test_subdir(
                        __file__,
                        ['data', 'encrypted_file'])
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_list15(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" list -r both -c "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    util.get_test_subdir(
                        __file__,
                        ['data', 'encrypted_file'])
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_list16(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" list -r extension "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    util.get_test_subdir(
                        __file__,
                        ['data', 'encrypted_file'])
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_list17(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" list -r extension -c "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    util.get_test_subdir(
                        __file__,
                        ['data', 'encrypted_file'])
                )
        )

        self.assertTrue(util.run(cmd))

class TestCase005(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.work_dir = util.get_test_subdir(__file__, cls.__name__)

        shutil.copytree(
            util.get_test_subdir(__file__, ['data', 'encrypted_file']),
            os.path.join(cls.work_dir, 'encrypted_file'))

    @classmethod
    def tearDownClass(cls):
        del cls.work_dir
        util.remove_test_subdir(__file__, cls.__name__)

    def setUp(self):
        self.work_dir = self.__class__.work_dir

    def tearDown(self):
        del self.work_dir

    def test_subcommand_remove(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" remove -h'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py')
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_remove2(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" remove "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    os.path.join(self.work_dir, 'encrypted_file')
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_remove3(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" remove -e "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    os.path.join(self.work_dir, 'encrypted_file')
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_remove4(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" remove -r encrypted "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    os.path.join(self.work_dir, 'encrypted_file')
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_remove5(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" remove -r decrypted "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    os.path.join(self.work_dir, 'encrypted_file')
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_remove6(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" remove -r both "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    os.path.join(self.work_dir, 'encrypted_file')
                )
        )

        self.assertTrue(util.run(cmd))

    def test_subcommand_remove7(self):
        if not sys.executable:
            return

        cmd = (
            '"%s" "%s" remove -r extension "%s"'
                % (
                    sys.executable,
                    os.path.join(util.get_launch_dir(__file__), 'main.py'),
                    os.path.join(self.work_dir, 'encrypted_file')
                )
        )

        self.assertTrue(util.run(cmd))

class TestCase101(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.work_dir = util.get_test_subdir(__file__, cls.__name__)

    @classmethod
    def tearDownClass(cls):
        del cls.work_dir
        util.remove_test_subdir(__file__, cls.__name__)

    def setUp(self):
        self.work_dir = self.__class__.work_dir

    def tearDown(self):
        del self.work_dir

    def test_slice(self):
        self.assertEqual('abcd'[:3], 'abc')

    def test_os_path_exists(self):
        self.assertFalse(os.path.exists(''))

    def test_crypto_util_padding_pad(self):
        case = b''
        case2 = b'0123456789'
        case3 = b'0123456789abcdef'
        case4 = b'0123456789abcdef0123456789'
        case5 = b'0123456789abcdef0123456789abcdef'

        data = case
        fill = 16 - len(data) % 16 if len(data) % 16 else 16
        self.assertEqual(pad(data, 16, 'pkcs7'), data + bytes([fill]) * fill)
        self.assertEqual(unpad(pad(data, 16, 'pkcs7'), 16, 'pkcs7'), data)

        data = case2
        fill = 16 - len(data) % 16 if len(data) % 16 else 16
        self.assertEqual(pad(data, 16, 'pkcs7'), data + bytes([fill]) * fill)
        self.assertEqual(unpad(pad(data, 16, 'pkcs7'), 16, 'pkcs7'), data)

        data = case3
        fill = 16 - len(data) % 16 if len(data) % 16 else 16
        self.assertEqual(pad(data, 16, 'pkcs7'), data + bytes([fill]) * fill)
        self.assertEqual(unpad(pad(data, 16, 'pkcs7'), 16, 'pkcs7'), data)

        data = case4
        fill = 16 - len(data) % 16 if len(data) % 16 else 16
        self.assertEqual(pad(data, 16, 'pkcs7'), data + bytes([fill]) * fill)
        self.assertEqual(unpad(pad(data, 16, 'pkcs7'), 16, 'pkcs7'), data)

        data = case5
        fill = 16 - len(data) % 16 if len(data) % 16 else 16
        self.assertEqual(pad(data, 16, 'pkcs7'), data + bytes([fill]) * fill)
        self.assertEqual(unpad(pad(data, 16, 'pkcs7'), 16, 'pkcs7'), data)

        data2 = b'0123456789abcdef0123456789abcdef'
        data3 = pad(data2, 16, 'pkcs7')
        self.assertEqual(unpad(data3, 16, 'pkcs7'), data2)
        self.assertEqual(data2[:16] + unpad(data3[16:48], 16, 'pkcs7'), data2)
        self.assertEqual(data2[:32] + unpad(data3[32:48], 16, 'pkcs7'), data2)

        self.assertRaises(Exception, unpad, b'abc', 16, 'pkcs7')
        self.assertRaises(Exception, unpad, b'0123456789abcdef', 16, 'pkcs7')
        self.assertRaises(Exception,
                          unpad,
                          bytes([8 for i in range(8)]),
                          16,
                          'pkcs7')
        self.assertRaises(Exception,
                          unpad,
                          bytes([(0 if i < 0 else i) for i in range(-7, 8)]),
                          16,
                          'pkcs7')
        self.assertRaises(Exception,
                          unpad,
                          bytes([16 for i in range(8)]),
                          16,
                          'pkcs7')
        self.assertRaises(Exception,
                          unpad,
                          bytes([i for i in range(16)]),
                          16,
                          'pkcs7')
        self.assertRaises(Exception,
                          unpad,
                          bytes([(i if i < 8 else 16) for i in range(24)]),
                          16,
                          'pkcs7')

    def test_crypto_cipher_aes(self):
        key = b'0123456789abcdef'
        iv = b'0123456789abcdef'
        data = (b'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW'
                b'XYZ_-')

        self.assertRaises(Exception, AES.new, b'abc', AES.MODE_CBC, iv)
        self.assertRaises(Exception, AES.new, key, AES.MODE_CBC, b'abc')

        a = AES.new(key, AES.MODE_CBC, iv)
        a2 = AES.new(key, AES.MODE_CBC, iv)
        self.assertEqual(
            a.encrypt(data[:48]) + a.encrypt(data[48:64]),
            a2.encrypt(data))

        a3 = AES.new(key, AES.MODE_CBC, iv)
        self.assertNotEqual(a3.encrypt(data), a3.encrypt(data))

        a4 = AES.new(key, AES.MODE_CBC, iv)
        a5 = AES.new(key, AES.MODE_CBC, iv)
        a6 = AES.new(key, AES.MODE_CBC, iv)
        self.assertNotEqual(
            a4.encrypt(data[:32]) + a5.encrypt(data[32:64]),
            a6.encrypt(data))

        a7 = AES.new(key, AES.MODE_CBC, iv)
        a8 = AES.new(key, AES.MODE_CBC, iv)
        self.assertEqual(a8.decrypt(a7.encrypt(data)), data)

        a9 = AES.new(key, AES.MODE_CBC, iv)
        self.assertRaises(Exception, a9.decrypt, a9.encrypt(data))

        a10 = AES.new(key, AES.MODE_CBC, iv)
        self.assertRaises(Exception, a10.encrypt, a10.decrypt(data))

        a11 = AES.new(key, AES.MODE_CBC, iv)
        self.assertRaises(Exception, a11.encrypt, b'abc')

        a12 = AES.new(key, AES.MODE_CBC, iv)
        self.assertRaises(Exception, a11.encrypt, b'0123456789abcdef01234567')

        a13 = AES.new(key, AES.MODE_CBC, iv)
        self.assertRaises(Exception, a12.decrypt, b'abc')

        a14 = AES.new(key, AES.MODE_CBC, iv)
        self.assertRaises(Exception, a12.decrypt, b'0123456789abcdef01234567')

    def test_os_path_is_file(self):
        self.assertFalse(os.path.isfile(True))
        self.assertFalse(os.path.isfile(b''))
        self.assertFalse(os.path.isfile(''))

        self.assertRaises(Exception, os.path.isfile, None)
        self.assertRaises(Exception, os.path.isfile, 5.5)
        self.assertRaises(Exception, os.path.isfile, [])
        self.assertRaises(Exception, os.path.isfile, {})

    def test_os_path_is_dir(self):
        self.assertFalse(os.path.isdir(True))
        self.assertFalse(os.path.isdir(4))
        self.assertFalse(os.path.isdir(b''))
        self.assertFalse(os.path.isdir(''))

        self.assertRaises(Exception, os.path.isdir, None)
        self.assertRaises(Exception, os.path.isdir, 5.5)
        self.assertRaises(Exception, os.path.isdir, [])
        self.assertRaises(Exception, os.path.isdir, {})

class TestCase102(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.work_dir = util.get_test_subdir(__file__, cls.__name__)

    @classmethod
    def tearDownClass(cls):
        del cls.work_dir
        util.remove_test_subdir(__file__, cls.__name__)

    def setUp(self):
        self.work_dir = self.__class__.work_dir

    def tearDown(self):
        del self.work_dir

    def test_is_printable_ascii(self):
        printable = (
            '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
            ''' `~!@#$%^&*()-_=+[{}]\\|;:'",<.>/?'''
        )
        log.info(printable)

        self.assertTrue(util.is_printable_ascii(printable))

        self.assertFalse(util.is_printable_ascii(3))
        self.assertFalse(util.is_printable_ascii(''))
        self.assertFalse(util.is_printable_ascii('abc\n'))
        self.assertFalse(util.is_printable_ascii('我是谁'))

    def test_is_supported_password(self):
        printable = (
            '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
            ''' `~!@#$%^&*()-_=+[{}]\\|;:'",<.>/?'''
        )
        log.info(printable)

        self.assertTrue(util.is_supported_password(printable))
        self.assertTrue(util.is_supported_password(''))

        self.assertFalse(util.is_supported_password(3))
        self.assertFalse(util.is_supported_password('abc\n'))
        self.assertFalse(util.is_supported_password('我是谁'))

    def test_is_supported_key(self):
        printable = (
            '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
            ''' `~!@#$%^&*()-_=+[{}]\\|;:'",<.>/?'''
        )
        log.info(printable)

        self.assertTrue(secret.is_supported_key(printable))

        self.assertFalse(secret.is_supported_key(3))
        self.assertFalse(secret.is_supported_key(''))
        self.assertFalse(secret.is_supported_key('abc\n'))
        self.assertFalse(secret.is_supported_key('我是谁'))

    def test_check_host(self):
        self.assertTrue(util.check_host('abc.ex'))
        self.assertTrue(util.check_host('abc.ex:56'))
        self.assertTrue(util.check_host('abc.ex : 56'))

        self.assertFalse(util.check_host(''))
        self.assertFalse(util.check_host(': 56'))
        self.assertFalse(util.check_host('abc.ex :'))
        self.assertFalse(util.check_host('abc.ex:abc:df'))

    def test_check_virtual_path(self):
        self.assertTrue(util.check_virtual_path('abc.ext'))
        self.assertTrue(util.check_virtual_path('abc.ex/a.txt'))
        self.assertTrue(util.check_virtual_path('abc/adfe/asatd'))

        self.assertFalse(util.check_virtual_path(''))
        self.assertFalse(util.check_virtual_path('//'))
        self.assertFalse(util.check_virtual_path('adfd//dfd/df'))

    def test_is_supported_url(self):
        self.assertTrue(util.is_supported_url('http://abc.ext'))
        self.assertTrue(util.is_supported_url('http://abc.ext:54'))
        self.assertTrue(util.is_supported_url('http://abc.ex:45/a.txt'))
        self.assertTrue(util.is_supported_url('https://adfe/asatd'))
        self.assertTrue(util.is_supported_url('https://adfed.dx : 35/'))
        self.assertTrue(util.is_supported_url('https://adfe.de:34/asatd/a.html'))

        self.assertFalse(util.is_supported_url(''))
        self.assertFalse(util.is_supported_url('//'))
        self.assertFalse(util.is_supported_url('adfd//dfd/df'))
        self.assertFalse(util.is_supported_url('adfd//dfd/df'))
        self.assertFalse(util.is_supported_url('adfd//dfd/df'))
        self.assertFalse(util.is_supported_url('http://dsflke//dfd/df'))
        self.assertFalse(util.is_supported_url('http://dsflke:df/dfd/df'))

    def test_get_url_root(self):
        self.assertEqual(
            util.get_url_root('http://ad.xe/sdt/d.html'),
            'http://ad.xe')
        self.assertEqual(
            util.get_url_root('http://ad.xe/d.html'),
            'http://ad.xe')
        self.assertEqual(
            util.get_url_root('http://ad.xe/'),
            'http://ad.xe')
        self.assertEqual(
            util.get_url_root('http://ad.xe'),
            'http://ad.xe')
        self.assertEqual(
            util.get_url_root('http://ad.xe/sdt/'),
            'http://ad.xe')
        self.assertEqual(
            util.get_url_root('http://ad.xe/sdt'),
            'http://ad.xe')
        self.assertEqual(
            util.get_url_root('http://ad.xe:45/sdt/d.html'),
            'http://ad.xe:45')
        self.assertEqual(
            util.get_url_root('http://ad.xe:45/d/'),
            'http://ad.xe:45')
        self.assertEqual(
            util.get_url_root('http://ad.xe:45/d'),
            'http://ad.xe:45')
        self.assertEqual(
            util.get_url_root('http://ad.xe:45/d.html'),
            'http://ad.xe:45')
        self.assertEqual(
            util.get_url_root('http://ad.xe:45/dfkl/dfsf/'),
            'http://ad.xe:45')
        self.assertEqual(
            util.get_url_root('http://ad.xe:45'),
            'http://ad.xe:45')
        self.assertEqual(
            util.get_url_root('http://ad.xe:45/'),
            'http://ad.xe:45')

    def test_get_relative_url_head(self):
        self.assertEqual(
            util.get_relative_url_head('http://ad.xe/sdt/d.html'),
            'http://ad.xe/sdt')
        self.assertEqual(
            util.get_relative_url_head('http://ad.xe/d.html'),
            'http://ad.xe')
        self.assertEqual(
            util.get_relative_url_head('http://ad.xe/'),
            'http://ad.xe')
        self.assertEqual(
            util.get_relative_url_head('http://ad.xe'),
            'http://ad.xe')
        self.assertEqual(
            util.get_relative_url_head('http://ad.xe/sdt/'),
            'http://ad.xe/sdt')
        self.assertEqual(
            util.get_relative_url_head('http://ad.xe/sdt'),
            'http://ad.xe')
        self.assertEqual(
            util.get_relative_url_head('http://ad.xe:45/sdt/d.html'),
            'http://ad.xe:45/sdt')
        self.assertEqual(
            util.get_relative_url_head('http://ad.xe:45/d/'),
            'http://ad.xe:45/d')
        self.assertEqual(
            util.get_relative_url_head('http://ad.xe:45/d'),
            'http://ad.xe:45')
        self.assertEqual(
            util.get_relative_url_head('http://ad.xe:45/d.html'),
            'http://ad.xe:45')
        self.assertEqual(
            util.get_relative_url_head('http://ad.xe:45/dfkl/dfsf/'),
            'http://ad.xe:45/dfkl/dfsf')
        self.assertEqual(
            util.get_relative_url_head('http://ad.xe:45'),
            'http://ad.xe:45')
        self.assertEqual(
            util.get_relative_url_head('http://ad.xe:45/'),
            'http://ad.xe:45')

    def test_is_supported_filename(self):
        self.assertTrue(util.is_supported_filename('abc'))

        self.assertFalse(util.is_supported_filename('\\'))
        self.assertFalse(util.is_supported_filename('/'))
        self.assertFalse(util.is_supported_filename(':'))
        self.assertFalse(util.is_supported_filename('*'))
        self.assertFalse(util.is_supported_filename('?'))
        self.assertFalse(util.is_supported_filename('"'))
        self.assertFalse(util.is_supported_filename('<'))
        self.assertFalse(util.is_supported_filename('>'))
        self.assertFalse(util.is_supported_filename('|'))

    def test_has_extension(self):
        self.assertTrue(util.has_extension('abc.kis', '.KIS'))
        self.assertTrue(util.has_extension('/abc/abc.KIS', '.kis'))

        self.assertFalse(util.has_extension('', ''))
        self.assertFalse(util.has_extension('abc.kis', ''))
        self.assertFalse(util.has_extension('', '.kis'))
        self.assertFalse(util.has_extension('abc.kis', '.TXT'))

    def test_is_encrypted_path(self):
        self.assertTrue(secret.is_encrypted_path('/abc/def.kis'))
        self.assertTrue(secret.is_encrypted_path('/abc/xdf.KIS'))

        self.assertFalse(secret.is_encrypted_path(''))
        self.assertFalse(secret.is_encrypted_path('.kis'))
        self.assertFalse(secret.is_encrypted_path('/abc/def.txt'))

    def test_generate_encrypted_path(self):
        self.assertEqual(
            secret.generate_encrypted_path('/abc/abc'),
            '/abc/abc.kis')
        self.assertEqual(
            secret.generate_encrypted_path('/abc/abc.txt'),
            '/abc/abc.txt.kis')
        self.assertEqual(
            secret.generate_encrypted_path('/abc/abc.kis'),
            '/abc/abc.kis.kis')

        self.assertEqual(
            secret.generate_encrypted_path(''),
            '')

    def test_generate_decrypted_path(self):
        self.assertEqual(
            secret.generate_decrypted_path('/abc/abc.txt.kis'),
            '/abc/abc.txt')
        self.assertEqual(
            secret.generate_decrypted_path('/abc/abc.kis.kis'),
            '/abc/abc.kis')

        self.assertEqual(
            secret.generate_decrypted_path(''),
            '')
        self.assertEqual(
            secret.generate_decrypted_path('/abc/abc.txt'),
            '')
        self.assertEqual(
            secret.generate_decrypted_path('/abc/.kis'),
            '')

    def test_is_hide(self):
        self.assertTrue(util.is_hide('.'))
        self.assertTrue(util.is_hide('..'))
        self.assertTrue(util.is_hide('.bash_history'))
        self.assertTrue(util.is_hide('.abc.txt'))
        self.assertTrue(util.is_hide('.git'))

        self.assertFalse(util.is_hide(''))
        self.assertFalse(util.is_hide('abc'))
        self.assertFalse(util.is_hide('abc.txt'))

    def test_strip_hide_dir(self):
        self.assertFalse(
            set(util.strip_hide_dir('/abc',
                                    ['.', '..', '.git', 'abc', 'def']))
            ^ set(['abc', 'def']))
        self.assertFalse(
            set(util.strip_hide_dir('/abc', ['.', '..', '.git'])) ^ set())
        self.assertFalse(
            set(util.strip_hide_dir('/abc', [])) ^ set())

    def test_is_encrypted_file(self):
        self.assertTrue(
            secret.is_encrypted_file(
                os.path.join(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    'case01.txt.kis')))

        self.assertFalse(secret.is_encrypted_file(''))
        self.assertFalse(
            secret.is_encrypted_file(
                os.path.join(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    'case00.txt.kis')))
        self.assertFalse(
            secret.is_encrypted_file(
                os.path.join(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    'case02.txt.kis')))
        self.assertFalse(
            secret.is_encrypted_file(
                os.path.join(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    'case03.txt')))
        self.assertFalse(
            secret.is_encrypted_file(
                os.path.join(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    'case04.txt.kis')))

    def test_is_decrypted_file(self):
        self.assertTrue(
            secret.is_decrypted_file(
                os.path.join(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    'case01.txt')))

        self.assertFalse(secret.is_decrypted_file(''))
        self.assertFalse(
            secret.is_decrypted_file(
                os.path.join(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    'case00.txt')))
        self.assertFalse(
            secret.is_decrypted_file(
                os.path.join(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    'case02.txt')))
        self.assertFalse(
            secret.is_decrypted_file(
                os.path.join(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    'case03.txt')))
        self.assertFalse(
            secret.is_decrypted_file(
                os.path.join(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    'case04.txt')))

    def test_is_requested_file_by_extension(self):
        self.assertTrue(
            util.is_requested_file_by_extension(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                'abc.txt',
                True,
                [
                    '.txt',
                    '.cfg'
                ]
            )
        )
        self.assertTrue(
            util.is_requested_file_by_extension(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                'abc.txt',
                True,
                []))
        self.assertTrue(
            util.is_requested_file_by_extension(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                'abc.info',
                False,
                [
                    '.txt',
                    '.cfg'
                ]
            )
        )
        self.assertTrue(
            util.is_requested_file_by_extension(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                'abc.txt',
                False,
                []))
        self.assertTrue(
            util.is_requested_file_by_extension(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                'abc.txt',
                False,
                ['']))

        self.assertFalse(
            util.is_requested_file_by_extension(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                'abc.txt',
                True,
                ['']))
        self.assertFalse(
            util.is_requested_file_by_extension(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                'abc.info',
                True,
                [
                    '.txt',
                    '.cfg'
                ]
            )
        )
        self.assertFalse(
            util.is_requested_file_by_extension(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                'abc.cfg',
                False,
                [
                    '.txt',
                    '.cfg'
                ]
            )
        )

    def test_is_requested_file_by_pattern(self):
        self.assertTrue(
            util.is_requested_file_by_pattern(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                'abbc.txt',
                False,
                [
                    'bb',
                    'xd'
                ]
            )
        )
        self.assertTrue(
            util.is_requested_file_by_pattern(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                'abc.txt',
                False,
                []))
        self.assertTrue(
            util.is_requested_file_by_pattern(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                'abc.info',
                True,
                [
                    'xy',
                    'ud'
                ]
            )
        )
        self.assertTrue(
            util.is_requested_file_by_pattern(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                'abc.txt',
                True,
                []))
        self.assertTrue(
            util.is_requested_file_by_pattern(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                'abc.txt',
                True,
                ['']))

        self.assertFalse(
            util.is_requested_file_by_pattern(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                'abc.txt',
                False,
                ['']))
        self.assertFalse(
            util.is_requested_file_by_pattern(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                'abc.info',
                False,
                [
                    'xd',
                    'de'
                ]
            )
        )
        self.assertFalse(
            util.is_requested_file_by_pattern(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                'abcdc.cfg',
                True,
                [
                    'bcd',
                    'dfs'
                ]
            )
        )

    def test_choose_files_to_encrypt(self):
        self.assertFalse(
            set(
                secret.choose_files_to_encrypt(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    [
                        'case01.txt',
                        'case01.txt.kis',
                        'case02.log',
                        'case02.log.kis',
                        'case03.info',
                        'case04.cfg',
                        'case04.cfg.kis'
                    ],
                    True,
                    True,
                    True,
                    [
                        '.log',
                        '.txt'
                    ],
                    True,
                    [
                        '02'
                    ]
                )
            )
            ^ set(
                [
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case01.txt')
                ]
            )
        )

        self.assertFalse(
            set(
                secret.choose_files_to_encrypt(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    [
                        'case01.txt',
                        'case01.txt.kis',
                        'case02.log',
                        'case02.log.kis',
                        'case03.info',
                        'case04.cfg',
                        'case04.cfg.kis'
                    ],
                    True,
                    False,
                    True,
                    [
                        '.log',
                        '.cfg',
                        '.kis'
                    ],
                    True,
                    [
                        '01',
                        '02'
                    ]
                )
            )
            ^ set(
                [
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case04.cfg'),
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case04.cfg.kis')
                ]
            )
        )

        self.assertFalse(
            set(
                secret.choose_files_to_encrypt(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    [
                        'case01.txt',
                        'case01.txt.kis',
                        'case02.log',
                        'case02.log.kis',
                        'case03.info',
                        'case04.cfg',
                        'case04.cfg.kis'
                    ],
                    True,
                    True,
                    True,
                    [],
                    True,
                    []
                )
            )
            ^ set(
                [
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case01.txt'),
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case02.log'),
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case02.log.kis'),
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case03.info'),
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case04.cfg'),
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case04.cfg.kis')
                ]
            )
        )

    def test_choose_files_to_decrypt(self):
        self.assertFalse(
            set(
                secret.choose_files_to_decrypt(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    [
                        'case01.txt',
                        'case01.txt.kis',
                        'case02.log',
                        'case02.log.kis',
                        'case03.info',
                        'case04.cfg',
                        'case04.cfg.kis'
                    ],
                    True,
                    True,
                    [
                        '02'
                    ]
                )
            )
            ^ set(
                [
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case01.txt.kis')
                ]
            )
        )

        self.assertFalse(
            set(
                secret.choose_files_to_decrypt(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    [
                        'case01.txt',
                        'case01.txt.kis',
                        'case02.log',
                        'case02.log.kis',
                        'case03.info',
                        'case04.cfg',
                        'case04.cfg.kis'
                    ],
                    True,
                    False,
                    [
                        '02'
                    ]
                )
            )
            ^ set([])
        )

        self.assertFalse(
            set(
                secret.choose_files_to_decrypt(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    [
                        'case01.txt',
                        'case01.txt.kis',
                        'case02.log',
                        'case02.log.kis',
                        'case03.info',
                        'case04.cfg',
                        'case04.cfg.kis'
                    ],
                    True,
                    True,
                    []
                )
            )
            ^ set(
                [
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case01.txt.kis')
                ]
            )
        )

    def test_choose_requested_file(self):
        self.assertFalse(
            set(
                secret.choose_requested_file(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    [
                        'case01.txt',
                        'case01.txt.kis',
                        'case02.log',
                        'case02.log.kis',
                        'case03.info',
                        'case04.cfg',
                        'case04.cfg.kis'
                    ],
                    True,
                    True,
                    False
                )
            )
            ^ set(
                [
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case01.txt.kis')
                ]
            )
        )

        self.assertFalse(
            set(
                secret.choose_requested_file(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    [
                        'case01.txt',
                        'case01.txt.kis',
                        'case02.log',
                        'case02.log.kis',
                        'case03.info',
                        'case04.cfg',
                        'case04.cfg.kis'
                    ],
                    True,
                    False,
                    True
                )
            )
            ^ set(
                [
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case01.txt')
                ]
            )
        )

        self.assertFalse(
            set(
                secret.choose_requested_file(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    [
                        'case01.txt',
                        'case01.txt.kis',
                        'case02.log',
                        'case02.log.kis',
                        'case03.info',
                        'case04.cfg',
                        'case04.cfg.kis'
                    ],
                    True,
                    True,
                    True
                )
            )
            ^ set([])
        )

    def test_count_requested_file(self):
        self.assertEqual(
            secret.count_requested_file(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                [
                    'case01.txt',
                    'case01.txt.kis',
                    'case02.log',
                    'case02.log.kis',
                    'case03.info',
                    'case04.cfg',
                    'case04.cfg.kis'
                ],
                True,
                True,
                False
            ),
            1
        )

        self.assertEqual(
            secret.count_requested_file(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                [
                    'case01.txt',
                    'case01.txt.kis',
                    'case02.log',
                    'case02.log.kis',
                    'case03.info',
                    'case04.cfg',
                    'case04.cfg.kis'
                ],
                True,
                False,
                True
            ),
            1
        )

        self.assertEqual(
            secret.count_requested_file(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                [
                    'case01.txt',
                    'case01.txt.kis',
                    'case02.log',
                    'case02.log.kis',
                    'case03.info',
                    'case04.cfg',
                    'case04.cfg.kis'
                ],
                True,
                True,
                True
            ),
            0
        )

    def test_choose_file_by_extension(self):
        self.assertFalse(
            set(
                util.choose_file_by_extension(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    [
                        'case01.txt',
                        'case01.txt.kis',
                        'case02.log',
                        'case02.log.kis',
                        'case03.info',
                        'case04.cfg',
                        'case04.cfg.kis'
                    ],
                    True,
                    '.kis'
                )
            )
            ^ set(
                [
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case01.txt.kis'),
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case02.log.kis'),
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case04.cfg.kis')
                ]
            )
        )

    def test_count_file_by_extension(self):
        self.assertEqual(
            util.count_file_by_extension(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                [
                    'case01.txt',
                    'case01.txt.kis',
                    'case02.log',
                    'case02.log.kis',
                    'case03.info',
                    'case04.cfg',
                    'case04.cfg.kis'
                ],
                True,
                '.kis'
            ),
            3
        )

    def test_choose_special_file(self):
        self.assertFalse(
            set(
                secret.choose_special_file(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    [
                        'case01.txt',
                        'case01.txt.kis',
                        'case02.log',
                        'case02.log.kis',
                        'case03.info',
                        'case04.cfg',
                        'case04.cfg.kis'
                    ],
                    True
                )
            )
            ^ set(
                [
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case02.log.kis'),
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case04.cfg.kis')
                ]
            )
        )

    def test_count_special_file(self):
        self.assertEqual(
            secret.count_special_file(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                [
                    'case01.txt',
                    'case01.txt.kis',
                    'case02.log',
                    'case02.log.kis',
                    'case03.info',
                    'case04.cfg',
                    'case04.cfg.kis'
                ],
                True
            ),
            2
        )

    def test_choose_empty_file(self):
        self.assertFalse(
            set(
                util.choose_empty_file(
                    util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                    [
                        'case01.txt',
                        'case01.txt.kis',
                        'case02.log',
                        'case02.log.kis',
                        'case03.info',
                        'case04.cfg',
                        'case04.cfg.kis'
                    ],
                    True
                )
            )
            ^ set(
                [
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case02.log'),
                    os.path.join(
                        util.get_test_subdir(__file__,
                                             ['data', 'encrypted_file']),
                        'case02.log.kis')
                ]
            )
        )

    def test_count_empty_file(self):
        self.assertEqual(
            util.count_empty_file(
                util.get_test_subdir(__file__, ['data', 'encrypted_file']),
                [
                    'case01.txt',
                    'case01.txt.kis',
                    'case02.log',
                    'case02.log.kis',
                    'case03.info',
                    'case04.cfg',
                    'case04.cfg.kis'
                ],
                True
            ),
            2
        )

class TestCase103(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.work_dir = util.get_test_subdir(__file__, cls.__name__)

        shutil.copyfile(
            os.path.join(util.get_test_subdir(__file__, ['data', 'file']),
                         'case01.jpeg'),
            os.path.join(cls.work_dir, 'case01.jpeg'))

    @classmethod
    def tearDownClass(cls):
        del cls.work_dir
        util.remove_test_subdir(__file__, cls.__name__)

    def setUp(self):
        self.work_dir = self.__class__.work_dir

    def tearDown(self):
        del self.work_dir

    def test_encrypt_single_file(self):
        self.assertTrue(
            secret.encrypt_single_file(
                os.path.join(self.work_dir, 'case01.jpeg'),
                'abc',
                True,
                8*1024*1024,
                True))

        self.assertTrue(
            util.compare_files(
                os.path.join(self.work_dir, 'case01.jpeg.kis'),
                os.path.join(util.get_test_subdir(__file__, ['data', 'file']),
                             'case01.jpeg.kis')))

class TestCase104(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.work_dir = util.get_test_subdir(__file__, cls.__name__)

        shutil.copyfile(
            os.path.join(util.get_test_subdir(__file__, ['data', 'file']),
                         'case01.jpeg.kis'),
            os.path.join(cls.work_dir, 'case01.jpeg.kis'))

    @classmethod
    def tearDownClass(cls):
        del cls.work_dir
        util.remove_test_subdir(__file__, cls.__name__)

    def setUp(self):
        self.work_dir = self.__class__.work_dir

    def tearDown(self):
        del self.work_dir

    def test_decrypt_single_file(self):
        self.assertTrue(
            secret.decrypt_single_file(
                os.path.join(self.work_dir, 'case01.jpeg.kis'),
                'abc',
                True,
                8*1024*1024,
                True))

        self.assertTrue(
            util.compare_files(
                os.path.join(self.work_dir, 'case01.jpeg'),
                os.path.join(util.get_test_subdir(__file__, ['data', 'file']),
                             'case01.jpeg')))

class UnorderedTestLoader(unittest.TestLoader):
    sortTestMethodsUsing = lambda self, x, y: -1


if __name__ == '__main__':
    util.set_log(__file__, '%s_v%s' % (__product__, __version__), 'debug')

    log.info('program version: %s %s', __product__, __version__)
    log.debug('command line: %s', sys.argv)

    unittest.main(testLoader=UnorderedTestLoader())
